﻿using Exhort.DbSet;
using Exhort.Entity;
using Exhort.Utility.Entities;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
using System.Reflection;

namespace Exhort.Service
{
    /// <summary>
    /// 树形业务基类
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    public abstract class TreeService<T> : OrderService<T> where T : TreeEntity, new()
    {
        /// <summary>
        /// 当前数据对象
        /// </summary>
        private TreeDbSet<T> dbSet
        {
            get { return db.DbSet<T, TreeDbSet<T>>(); }
        }

        /// <summary>
        /// 根据主键获取子集
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>列表</returns>
        public virtual List<T> Children(string key)
        {
            return dbSet.Children(key);
        }

        /// <summary>
        /// 根据主键获取对象和子集
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>列表</returns>
        public virtual List<T> EntityAndChildren(string key)
        {
            return dbSet.EntityAndChildren(key);
        }

        /// <summary>
        /// 设置排序
        /// </summary>
        /// <param name="id">编号</param>
        /// <param name="order">顺序</param>
        /// <param name="pid">父级</param>
        /// <returns>操作结果</returns>
        public virtual ServiceResult Order(string id, string order, string pid)
        {
            return LineResult(dbSet.Order(id, order, pid), "排序成功调整", "没有可调换顺序的数据");
        }

        /// <summary>
        /// 拼装树形结构
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public virtual List<Hashtable> AssembleTree(List<T> list)
        {
            Hashtable GetHash(object obj)
            {
                Hashtable hst = new Hashtable();
                var type = obj.GetType();
                foreach (PropertyInfo pi in type.GetProperties())
                {
                    PropertyInfo property = type.GetProperty(pi.Name);
                    hst.Add(pi.Name, property.GetValue(obj, null));
                }
                return hst;
            }

            List<Hashtable> AssembleChildren(string pid)
            {
                List<Hashtable> hashs = new List<Hashtable>();

                var children = list.Where(m => m.Pid.Equals(pid));

                foreach (var item in children)
                {
                    var hash = GetHash(item);

                    var hashChildren = AssembleChildren(item.ID);

                    if (hashChildren != null)
                    {
                        hash.Add("children", hashChildren);
                    }

                    hashs.Add(hash);
                }

                return hashs.Count > 0 ? hashs : null;
            }

            return AssembleChildren("0");
        }
    }
}
